package com.beauty.logistics.service.impl;

import com.beauty.logistics.dto.ShipmentRequest;
import com.beauty.logistics.dto.ShipmentResponse;
import com.beauty.logistics.entity.Shipment;
import com.beauty.logistics.entity.Shipment.ShipmentStatus;
import com.beauty.logistics.exception.LogisticsException;
import com.beauty.logistics.repository.ShipmentRepository;
import com.beauty.logistics.service.ShipmentService;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ShipmentServiceImpl implements ShipmentService {
    
    private final ShipmentRepository shipmentRepository;
    
    @Override
    @Transactional
    public ShipmentResponse createShipment(ShipmentRequest shipmentRequest) {
        Shipment shipment = new Shipment();
        shipment.setOrderId(shipmentRequest.getOrderId());
        shipment.setShippingMethod(shipmentRequest.getShippingMethod());
        shipment.setCarrierName(shipmentRequest.getCarrierName());
        shipment.setCustomerId(shipmentRequest.getCustomerId());
        shipment.setStatus(ShipmentStatus.PENDING);
        shipment.setEstimatedDeliveryDate(shipmentRequest.getEstimatedDeliveryDate());
        shipment.setOriginAddress(shipmentRequest.getOriginAddress());
        shipment.setDestinationAddress(shipmentRequest.getDestinationAddress());
        shipment.setPackageDimensions(shipmentRequest.getPackageDimensions());
        shipment.setPackageWeight(shipmentRequest.getPackageWeight());
        shipment.setNotes(shipmentRequest.getNotes());
        
        // 生成跟踪号
        shipment.setTrackingNumber(generateTrackingNumber(shipmentRequest.getCarrierName()));
        
        Shipment savedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(savedShipment);
    }
    
    @Override
    public ShipmentResponse getShipmentById(Long id) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        return ShipmentResponse.fromEntity(shipment);
    }
    
    @Override
    public ShipmentResponse getShipmentByTrackingNumber(String trackingNumber) {
        Shipment shipment = shipmentRepository.findByTrackingNumber(trackingNumber)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，跟踪号: " + trackingNumber));
        return ShipmentResponse.fromEntity(shipment);
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByOrderId(String orderId) {
        return shipmentRepository.findByOrderId(orderId)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByCustomerId(String customerId) {
        return shipmentRepository.findByCustomerId(customerId)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByStatus(ShipmentStatus status) {
        return shipmentRepository.findByStatus(status)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByCarrierName(String carrierName) {
        return shipmentRepository.findByCarrierName(carrierName)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByShippingDateRange(LocalDateTime start, LocalDateTime end) {
        return shipmentRepository.findByShippingDateBetween(start, end)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getShipmentsByEstimatedDeliveryDateRange(LocalDateTime start, LocalDateTime end) {
        return shipmentRepository.findByEstimatedDeliveryDateBetween(start, end)
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<ShipmentResponse> getAllShipments() {
        return shipmentRepository.findAll()
                .stream()
                .map(ShipmentResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    @Transactional
    public ShipmentResponse updateShipmentStatus(Long id, ShipmentStatus status) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        
        shipment.setStatus(status);
        
        if (status == ShipmentStatus.SHIPPED && shipment.getShippingDate() == null) {
            shipment.setShippingDate(LocalDateTime.now());
        } else if (status == ShipmentStatus.DELIVERED && shipment.getActualDeliveryDate() == null) {
            shipment.setActualDeliveryDate(LocalDateTime.now());
        }
        
        Shipment updatedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(updatedShipment);
    }
    
    @Override
    @Transactional
    public ShipmentResponse updateShipmentTracking(Long id, String trackingNumber) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        
        // 检查跟踪号是否已存在
        shipmentRepository.findByTrackingNumber(trackingNumber)
                .ifPresent(existingShipment -> {
                    if (!existingShipment.getId().equals(id)) {
                        throw new LogisticsException("跟踪号已存在: " + trackingNumber);
                    }
                });
        
        shipment.setTrackingNumber(trackingNumber);
        
        Shipment updatedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(updatedShipment);
    }
    
    @Override
    @Transactional
    public ShipmentResponse updateShipmentDeliveryDate(Long id, LocalDateTime estimatedDeliveryDate) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        
        shipment.setEstimatedDeliveryDate(estimatedDeliveryDate);
        
        Shipment updatedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(updatedShipment);
    }
    
    @Override
    @Transactional
    public ShipmentResponse markShipmentAsShipped(Long id, LocalDateTime shippingDate) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        
        shipment.setStatus(ShipmentStatus.SHIPPED);
        shipment.setShippingDate(shippingDate != null ? shippingDate : LocalDateTime.now());
        
        Shipment updatedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(updatedShipment);
    }
    
    @Override
    @Transactional
    public ShipmentResponse markShipmentAsDelivered(Long id, LocalDateTime deliveryDate) {
        Shipment shipment = shipmentRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("物流单不存在，ID: " + id));
        
        shipment.setStatus(ShipmentStatus.DELIVERED);
        shipment.setActualDeliveryDate(deliveryDate != null ? deliveryDate : LocalDateTime.now());
        
        Shipment updatedShipment = shipmentRepository.save(shipment);
        return ShipmentResponse.fromEntity(updatedShipment);
    }
    
    @Override
    @Transactional
    public void deleteShipment(Long id) {
        if (!shipmentRepository.existsById(id)) {
            throw new EntityNotFoundException("物流单不存在，ID: " + id);
        }
        shipmentRepository.deleteById(id);
    }
    
    private String generateTrackingNumber(String carrierName) {
        String prefix;
        
        switch (carrierName.toUpperCase()) {
            case "顺丰快递":
            case "SF":
                prefix = "SF";
                break;
            case "中通快递":
            case "ZTO":
                prefix = "ZT";
                break;
            case "DHL":
                prefix = "DH";
                break;
            default:
                prefix = "TR";
        }
        
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10).toUpperCase();
        return prefix + LocalDateTime.now().getYear() + uuid;
    }
} 